<template>
  <div class="component-banner">
    <div class="loading" v-if="list.length === 0">
      <span class="iconfont">&#xe66b;</span>
    </div>
    <div class="banner-wrapper" :style="wrapperStyle" v-else ref="bannerWrapper" :class="{'banner-wrapper-none-animate':noneAnimate}" @touchstart="touchstart" @touchend="touchend" @touchmove="move">
      <div class="subItem" v-for="(item,index) in bannerData" :key="index" :style="subItemStyle" :data-index="item.$$index">
        <img :src="item[conf.field.thumb]" >
      </div>
    </div>
    <div class="page" v-if="list.length > 0">
      <ul>
        <template v-for="n in list.length">
          <li :class="{on:(n-1)===currentBannerElement.$$index}" :data-n="n-1" :data-index="currentBannerElement.$$index"></li>
        </template>
      </ul>
    </div>
  </div>
</template>

<script>
  export default {
    name: "banner",
    props:{
      list:{
        type:Array,
        required:true
      },
      config:{
        type:Object,
        default:function(){
          return {};
        }
      }
    },
    data(){
      return {
        bannerData:[],
        conf:Object.assign({
          duration:1000,
          isPage:true,
          field:{
            thumb:'thumb',
            src:'src',
            title:'title'
          }
        },this.config),
        wrapperStyle:{
          width:0,
          transform:'translate3d(0,0,0)'
        },
        subItemStyle:{
          width:0
        },
        timeoutIndex:null,
        nextTimeoutIndex:null,
        prevTimeoutIndex:null,
        index:1, // 对应当前滚动到的bannerData的索引,
        time:1000,
        noneAnimate:false,
        touchX:null,
        percent:null
      };
    },
    methods:{
      init(){
        this.list.forEach((el,index)=>{
          el.$$index = index;
        });
        this.bannerData = [this.list[this.list.length-1]].concat(this.list).concat([this.list[0]]);
        this.index = 1;
        this.wrapperStyle.width = this.wrapperWidth+'%';
        this.subItemStyle.width = this.itemWidth+'%';
        this.time = this.conf.duration;
        this.run();
        this.autoPlay();
      },
      play(){
        if(this.list.length<2){
          return false;
        }
        this.next();
      },
      run(){
        this.wrapperStyle.transform = 'translate3d('+(this.index * -1 * this.itemWidth)+'%,0,0)';
      },
      autoPlay(){
        this.stop();
        this.timeoutIndex = setTimeout(this.play,this.time);
      },
      next(){
        this.stop();
        this.index+=1;
        if(this.index>this.bannerData.length-1){
          // 8 1 2 3 4 5 6 7 8 1
          // 滚动到最后一个元素时，秒切换回第二个元素（第二个元素和最后一个元素是一样的），然后再this.time后有动画效果地切换到下一个元素
          this.index = 1;
          this.noneAnimate = true;
          this.run();
          setTimeout(()=>{
            this.noneAnimate = false;
            this.index+=1;
            this.run();
            this.autoPlay();
          },30);
          return false;
        }else{
          this.run();
        }
        this.autoPlay();
      },
      prev(){
        this.stop();
        this.index-=1;
        if(this.index<0){
          this.index = this.bannerData.length-2;
          this.noneAnimate = true;
          this.run();
          setTimeout(()=>{
            this.noneAnimate = false;
            this.index-=1;
            this.run();
            this.autoPlay();
          },30);
          return false;
        }else{
          this.run();
        }
        this.autoPlay();
      },
      stop(){
        if(this.timeoutIndex){
          clearTimeout(this.timeoutIndex);
        }
      },
      touchstart(e){
        this.touchX = e.changedTouches[0].clientX;
        this.noneAnimate = true;
        this.stop();
        if(this.index>=this.bannerData.length-1){
          this.index = 1;
          this.noneAnimate = true;
          this.run();
        }else if(this.index<=0){
          this.index = this.bannerData.length-2;
          this.noneAnimate = true;
          this.run();
        }
      },
      touchend(e){
        this.touchX = null;
        this.noneAnimate = false;

        if(Math.abs(this.percent)>0.05){
          if(this.percent>0){
            this.prev();
          }else{
            this.next();
          }
        }else{
          this.run();
          this.autoPlay();
        }
      },
      move(e){
        const bodyWidth = document.body.clientWidth;
        const touches = e.changedTouches[0];
        const diff = touches.clientX-this.touchX;
        const percent = diff / bodyWidth;
        this.percent = percent;
        this.wrapperStyle.transform = 'translate3d('+( (this.index-percent) * -1 * this.itemWidth)+'%,0,0)';
      },
    },
    computed:{
      wrapperWidth(){
        return this.bannerData.length * 100;
      },
      itemWidth(){
        return 100 / this.bannerData.length;
      },
      currentBannerElement(){
        return this.bannerData[this.index];
      }
    },
    mounted(){
      this.init();
    },
    watch:{
      list:function(){
        this.init();
      }
    }
  }
</script>

<style scoped lang="less">
  div.component-banner{
    width:100%;
    height:10em;
    overflow:hidden;
    position:relative;

    @keyframes loadingRotate {
      to{
        transform:rotate(360deg);
      }
      from{
        transform:rotate(0);
      }
    }
    .loading{
      display:block;
      width:auto;
      height:100%;
      line-height:10em;
      margin:0 5px;
      box-sizing:border-box;
      background-color:#fff;
      position:relative;

      span.iconfont{
        display:block;
        width:1em;
        height:1em;
        line-height:1em;
        font-size:2em;
        position:relative;
        top:50%;
        left:50%;
        margin: -0.5em 0 0 -0.5em;
        animation:loadingRotate 1s;
        animation-iteration-count: infinite;
        animation-timing-function: linear;
        color:#C0C4CC;
      }
    }

    .banner-wrapper-none-animate{
      transition-duration:0s !important;
      /*-webkit-transition-duration:0s !important;*/
      /*-moz-transition-duration:0s !important;*/
      /*-ms-transition-duration:0s !important;*/
      /*-o-transition-duration:0s !important;*/
      /*transition:none !important;*/
    }
    .banner-wrapper{
      height:100%;
      transition:transform .3s;

      .subItem{
        font-size:1em;
        width:0;
        display:inline-block;
        padding:0 5px;
        box-sizing:border-box;
        height:100%;
        overflow:hidden;

        img{
          display:block;
          width:100%;
          /*height:100%;*/
          height:auto;
          border-radius:.3em;

        }
      }
    }

    @pageSize:1em;
    .page{
      position:absolute;
      z-index:10;
      left:50%;
      transform:translateX(-50%);
      bottom:.5em;
      width:auto;
      height:@pageSize;
      line-height:@pageSize;

      ul{

        li{
          display:inline-block;
          width:@pageSize/2;
          height:@pageSize/2;
          border-radius:@pageSize/4;
          background-color:#fff;
          margin:0 @pageSize/6;
        }

        li.on{
          background-color:#DF4338;
        }
      }
    }
  }
</style>
